import { action, computed, makeObservable, observable, toJS } from "mobx";
import { Bone } from "../animation/models/Bone";
import { DisplayType } from "../animation/models/Display";

export type SceneSlot = {
    name: string;
    parent: string;
};

export type SceneBone = {
    name: string;
    parent: string;
    isFold: boolean;
    level: number;
    isSelected: boolean;
    children: string[];
    slot: SceneSlot[];
};

export type CreateDisplayData = {
    boneName: string;
    path: string;
    slot: string;
    name: string;
};

////////////////////////
export type SceneDisplay = {
    type: DisplayType;
    name: string;
};

// export type SceneSkinSlot = {
//     name: string;
//     display: SceneDisplay[];
// };

// export type SceneSkin = {
//     name: string;
//     slot: SceneSkinSlot[];
// };

export type SceneSkinSlotMap = Map<string, SceneDisplay[]>;
export type SceneSkinMap = Map<string, SceneSkinSlotMap>;

export class SceneStore {
    boneMap = new Map<string, SceneBone>();
    skin = new Map<string, SceneSkinSlotMap>();
    curSkinName = "default";

    constructor() {
        this.boneMap.set("root", {
            name: "root",
            parent: "",
            isFold: false,
            level: 0,
            isSelected: false,
            children: [],
            slot: [],
        });

        makeObservable(this, {
            boneMap: observable,
            skin: observable,
            curSkinName: observable,
            addBone: action,
            changeFold: action,
            unFoldBone: action,
            setSelected: action,
            addSlot: action,
            addSkinSlot: action,
            addDisplay: action,
            addSkin: action,
            curSkin: computed,
        });
    }

    public addBone(parent: string, model: Bone, level: number) {
        if (level === 0) {
            return;
        }

        let parentBone = this.boneMap.get(parent);
        if (!parentBone) {
            return;
        }

        this.boneMap.set(model.name, {
            name: model.name,
            parent: parentBone.name,
            isFold: false,
            level: level,
            isSelected: false,
            children: [],
            slot: [],
        });

        parentBone.children.push(model.name);
        this.unFoldBone(parentBone.name);
    }

    public changeFold(boneName: string) {
        let bone = this.boneMap.get(boneName);
        if (bone) {
            bone.isFold = !bone.isFold;
        }
    }

    public unFoldBone(boneName: string) {
        let bone = this.boneMap.get(boneName);
        if (bone) {
            bone.isFold = false;
            if (bone.parent !== "") {
                this.unFoldBone(bone.parent);
            }
        }
    }

    public setSelected(boneName: string) {
        for (let item of this.boneMap.values()) {
            item.isSelected = false;
        }

        let bone = this.boneMap.get(boneName);
        if (bone) {
            bone.isSelected = true;
        }
    }

    public addSlot(parent: string, name: string) {
        let bone = this.boneMap.get(parent);
        if (bone) {
            bone.slot.push({
                name: name,
                parent: parent,
            });
        }
    }

    public addSkinSlot(slotName: string, skinName = "default") {
        let skin = this.skin.get(skinName);
        if (!skin) {
            return;
        }

        if (skin.has(slotName)) {
            return;
        }

        skin.set(slotName, []);
    }

    public addDisplay(slotName: string, displayName: string, skinName = "default") {
        let skin = this.skin.get(skinName);
        if (!skin) {
            return;
        }

        let sceneDisplayList = skin.get(slotName);
        if (!sceneDisplayList) {
            return;
        }

        sceneDisplayList.push({
            name: displayName,
            type: DisplayType.Image,
        });
    }

    get curSkin() {
        return this.skin.get(this.curSkinName);
    }

    public addSkin(name: string) {
        if (this.skin.has(name)) {
            return;
        }

        this.skin.set(name, new Map<string, SceneDisplay[]>());
    }

    public dump() {
        console.log("dump scene store", toJS(this.boneMap), toJS(this.skin));
    }

}

export default new SceneStore();
